package com.gy.nio;

import io.netty.channel.socket.ServerSocketChannelConfig;
import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.Scanner;

public class NIOTest {

    public static void main(String[] args) throws IOException {
        client();
    }

    public static void client() throws IOException {
        //或取通道，默认就是阻塞
        SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("localhost", 12121));

        //将阻塞的套接字变为非阻塞
        sChannel.configureBlocking(false);

        //创建指定大小的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String inputStr = scanner.next();

            //发送数据给服务端 直接将数据存储到buf
            buf.put((LocalDateTime.now().toString() + ": " + inputStr).getBytes());

            //将缓冲区变为读模式
            buf.flip();

            //将缓冲区数据写入到sChannel中
            sChannel.write(buf);

            buf.clear();
        }

        //关闭通道
        sChannel.close();

    }

    @Test
    public void server() throws IOException {
        //或取通道
        ServerSocketChannel ssChannel = ServerSocketChannel.open();
        //将组设的套接组设置为非阻塞的
        ssChannel.configureBlocking(false);

        //绑定端口号
        ssChannel.bind(new InetSocketAddress("localhost", 12121));

        //创建选择器对象
        Selector selector = Selector.open();

        //将通道注册到选择器上  指定监听类型
        ssChannel.register(selector, SelectionKey.OP_ACCEPT);

        //通过轮询方式或取选择器上就绪的事件 如果大于0，至少有一个selectionKey准备就绪
        while (selector.select() > 0) {
            //获取当前选择器中所有注册的选择器（已经就绪的监听事件）
            Iterator<SelectionKey> it = selector.selectedKeys().iterator();

            // 迭代获取已经准备就绪的选择器
            while (it.hasNext()) {
                //获取已经准备就绪的selectionKey
                SelectionKey sk = it.next();
                if (sk.isAcceptable()) {
                    //调用accpet监听
                    SocketChannel sChannel = ssChannel.accept();
                    //将sChannel设置为非阻塞
                    sChannel.configureBlocking(false);
                    //将该通道注册到选择器上  选择器能够监听这个通道，同样也需要完成注册
                    sChannel.register(selector, SelectionKey.OP_READ);//注册可以写的状态

                } else if (sk.isReadable()) {
                    //如果读状态已经准备就绪 开始读取数据
                    //获取选择器上读状态准备就绪的通道
                    SocketChannel sChannel = (SocketChannel) sk.channel();
                    //读取客户发送的数据
                    ByteBuffer buf = ByteBuffer.allocate(1024);
                    int len = 0;
                    while ((len = sChannel.read(buf)) > 0) {
                        buf.flip();
                        System.out.println(new String(buf.array(), 0, len));
                        buf.clear();
                    }
                }
                //selectionKey使用完毕后不移除 将一直有效
                it.remove();

            }

        }


    }
}
